package com.ymx.darling.tenant;

import com.ymx.darling.bean.entity.BeanInfo;
import com.ymx.darling.bean.entity.FieldInfo;
import com.ymx.darling.wrapper.Wrapper;
import com.ymx.darling.bean.entity.TableAlias;
import com.ymx.darling.wrapper.fragment.WhereSegment;

import java.util.Objects;
import java.util.function.Supplier;

public class TenantManager {
    /**
     * 保存线程本地的状态
     */
    private static final ThreadLocal<Boolean> skipFlags = new ThreadLocal<>();


    private static TenantFactory tenantFactory;


    public static <T> T execWithoutTenantId(Supplier<T> supplier) {
        T result;
        try {
            skip();
            result = supplier.get();
        } finally {
            restore();
        }

        return result;
    }


    public static void execWithoutTenantId(Runnable runnable) {
        try {
            skip();
            runnable.run();
        } finally {
            restore();
        }
    }


    /**
     * 临时关闭逻辑删除
     */
    private static void skip() {
        skipFlags.set(Boolean.TRUE);
    }


    /**
     * 恢复逻辑删除设置
     */
    private static void restore() {
        skipFlags.remove();
    }


    /**
     * 判断是否临时跳过逻辑删除
     * @return boolean
     */
    private static boolean isSkip() {
        return skipFlags.get() == Boolean.TRUE;
    }


    public static Object getTenantIdValue() {
        if (Objects.nonNull(tenantFactory)) {
            return tenantFactory.getTenantId();
        }
        return null;
    }


    public static boolean isTenantEnabled(BeanInfo beanInfo) {
        return !isSkip() &&
                Objects.nonNull(tenantFactory) &&
                Objects.nonNull(beanInfo) &&
                Objects.nonNull(beanInfo.getTenantIdColumn());
    }


    public static void setTenantFactory(TenantFactory tenantFactory) {
        TenantManager.tenantFactory = tenantFactory;
    }


    /**
     * 设置租户条件
     * @param tableName 表名(包含别名)
     * @param wrapper wrapper
     */
    public static void addConditionByWrapper(FieldInfo tenantIdFieldInfo, String tableName, Wrapper<?> wrapper) {
        String tenantIdColumn = tenantIdFieldInfo.getColumn();
        TableAlias tableAlias = TableAlias.splitTableAndAlias(tableName);
        String conditionTableName = tableAlias.hasAlias() ? tableAlias.getAliasName() : tableName;
        String columnName = String.format("%s.%s", conditionTableName, tenantIdColumn);
        Object tenantId = tenantFactory.getTenantId();
        wrapper.eq(columnName, tenantId);
    }


    /**
     * 设置租户条件
     * @param tableName 表名(包含别名)
     * @param whereSegment whereSegment
     */
    public static void addConditionByWhere(FieldInfo tenantIdFieldInfo, String tableName, WhereSegment whereSegment) {
        String tenantIdColumn = tenantIdFieldInfo.getColumn();
        TableAlias tableAlias = TableAlias.splitTableAndAlias(tableName);
        String conditionTableName = tableAlias.hasAlias() ? tableAlias.getAliasName() : tableName;
        String columnName = String.format("%s.%s", conditionTableName, tenantIdColumn);
        Object tenantId = tenantFactory.getTenantId();
        whereSegment.eq(columnName, tenantId);
    }
}